package com.yunchao.feature.base.domain.utils

import android.content.Context
import android.os.Build
import android.os.Environment
import android.util.Log
import timber.log.Timber
import java.io.File
import java.io.FileWriter
import java.io.IOException
import java.text.SimpleDateFormat
import java.util.*
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
import java.util.concurrent.atomic.AtomicBoolean
import java.util.concurrent.atomic.AtomicLong

/**
* 自定义 Timber 的 Tree 实现，用于将日志写入文件
*
* @param context 上下文对象，用于获取文件存储路径和版本信息
* @param maxLogFiles 最大保留的日志文件数量（默认7个）
* @param maxFileSize 单个日志文件最大大小（MB，默认500MB）
* @param executor 用于执行日志写入任务的线程池（默认单线程池）
* @param includeDeviceInfo 是否在日志文件开头包含设备信息（默认true）
*/
class FileLoggingTree(
    private val context: Context,
    private val maxLogFiles: Int = 7,
    private val maxFileSize: Int = 500, // 500MB
    private val executor: ExecutorService = Executors.newSingleThreadExecutor(),
    private val includeDeviceInfo: Boolean = true
) : Timber.Tree() {

    companion object {
        private const val LOG_FILE_PREFIX = "YC-App-Log_"
        private const val LOG_FILE_SUFFIX = ".log"
        private const val MB = 1024 * 1024L
        private const val LOG_HEADER_DIVIDER = "================================================"
    }

    // 使用原子布尔值确保清理操作只执行一次
    private val isCleanupScheduled = AtomicBoolean(false)

    // 日志目录（应用专属目录，无需权限）
    private val logDir: File by lazy {
        File(context.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), "logs").apply {
            if (!exists()) mkdirs()
        }
    }

    // 线程安全的日期格式器
    private val dateFormat: ThreadLocal<SimpleDateFormat> = ThreadLocal.withInitial {
        SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).apply {
            timeZone = TimeZone.getDefault()
        }
    }

    // 线程安全的时间格式器
    private val timeFormat: ThreadLocal<SimpleDateFormat> = ThreadLocal.withInitial {
        SimpleDateFormat("HH:mm:ss.SSS", Locale.getDefault()).apply {
            timeZone = TimeZone.getDefault()
        }
    }

    // 当前日志文件引用
    @Volatile
    private var currentLogFile: File? = null

    // 当前日志文件大小
    private val currentFileSize = AtomicLong(0)

    // 应用版本信息（延迟初始化）
    private val appVersionInfo by lazy {
        buildString {
            append("$LOG_HEADER_DIVIDER\n")
            append("=== Application Info ===\n")
            append("Package Name: ${context.packageName}\n")
            append("Version Name: ${getVersionName()}\n")
            append("Version Code: ${getVersionCode()}\n")
            append("Build Time: ${getBuildTime()}\n")

            try {
                // 添加BuildConfig信息（如果可用）
                val buildConfigClass = Class.forName("${context.packageName}.BuildConfig")
                append("Build Type: ${getStaticField(buildConfigClass, "BUILD_TYPE")}\n")
                append("Flavor: ${getStaticField(buildConfigClass, "FLAVOR")}\n")

                // 尝试获取Git提交信息（如果配置了）
                try {
                    append("Git Commit: ${getStaticField(buildConfigClass, "GIT_COMMIT_HASH")}\n")
                } catch (e: Exception) {
                    // 忽略，可能没有配置
                }
            } catch (e: Exception) {
                // 忽略BuildConfig信息获取失败
            }

            if (includeDeviceInfo) {
                append("\n=== Device Info ===\n")
                append("Manufacturer: ${Build.MANUFACTURER}\n")
                append("Model: ${Build.MODEL}\n")
                append("Device: ${Build.DEVICE}\n")
                append("Android Version: ${Build.VERSION.RELEASE} (SDK ${Build.VERSION.SDK_INT})\n")
            }

            append(LOG_HEADER_DIVIDER)
            append("\n\n") // 添加空行分隔头部和日志内容
        }
    }

    override fun log(priority: Int, tag: String?, message: String, t: Throwable?) {
        executor.execute {
            try {
                val logFile = getCurrentLogFile()
                val logContent = buildLogContent(priority, tag, message, t)

                // 检查文件大小是否超过限制
                if (currentFileSize.get() > maxFileSize * MB) {
                    rotateLogFile()
                }

                writeToFile(logFile, logContent)

                // 延迟清理旧日志（只执行一次）
                if (!isCleanupScheduled.getAndSet(true)) {
                    executor.submit {
                        cleanOldLogs()
                        isCleanupScheduled.set(false)
                    }
                }
            } catch (e: Exception) {
                Timber.tag("FileLogging").e(e, "Failed to write log")
            }
        }
    }

    /**
    * 构建日志内容
    */
    private fun buildLogContent(priority: Int, tag: String?, message: String, t: Throwable?): String {
        return buildString {
            append("${timeFormat.get()?.format(Date())} ")
            append("[${priorityToChar(priority)}/${tag ?: "NO_TAG"}] ")
            append(message)
            append("\n")
            t?.let {
                append(it.stackTraceToString())
                append("\n\n")
            }
        }
    }

    /**
    * 获取当前日志文件（如果不存在或日期变更则创建新文件）
    */
    private fun getCurrentLogFile(): File {
        val today = dateFormat.get()?.format(Date())
        val currentFile = currentLogFile

        return if (currentFile != null && currentFile.name.startsWith("$LOG_FILE_PREFIX$today")) {
            currentFile
        } else {
            synchronized(this) {
                val newFile = File(logDir, "$LOG_FILE_PREFIX$today$LOG_FILE_SUFFIX")
                if (newFile != currentFile) {
                    // 新文件或日期变更，重置文件大小并写入头部信息
                    currentLogFile = newFile
                    currentFileSize.set(0)

                    // 如果是新创建的文件，写入版本信息
                    if (!newFile.exists() || newFile.length() == 0L) {
                        writeToFile(newFile, appVersionInfo)
                    } else {
                        // 已有文件，获取当前大小
                        currentFileSize.set(newFile.length())
                    }
                }
                newFile
            }
        }
    }

    /**
    * 当日志文件过大时轮转文件
    */
    private fun rotateLogFile() {
        synchronized(this) {
            val currentFile = currentLogFile ?: return
            val timestamp = SimpleDateFormat("HHmmss", Locale.getDefault()).format(Date())
            val rotatedFile = File(
                logDir,
                currentFile.name.replace(LOG_FILE_SUFFIX, "_$timestamp$LOG_FILE_SUFFIX")
            )

            if (currentFile.renameTo(rotatedFile)) {
                currentLogFile = File(logDir, currentFile.name)
                currentFileSize.set(0)
                // 新文件写入头部信息
                writeToFile(currentLogFile!!, appVersionInfo)
            }
        }
    }

    /**
    * 写入日志到文件
    */
    private fun writeToFile(file: File, content: String) {
        try {
            FileWriter(file, true).buffered().use { writer ->
                writer.append(content)
                currentFileSize.addAndGet(content.length.toLong())
            }
        } catch (e: IOException) {
            throw IOException("Failed to write log to ${file.absolutePath}", e)
        }
    }

    /**
    * 清理过期日志文件
    */
    private fun cleanOldLogs() {
        logDir.listFiles()?.let { files ->
            if (files.size > maxLogFiles) {
                files.sortedBy { it.lastModified() }
                    .take(files.size - maxLogFiles)
                    .forEach {
                        try {
                            it.delete()
                        } catch (e: SecurityException) {
                            Timber.tag("FileLogging").w("Failed to delete old log file: ${it.name}")
                        }
                    }
            }
        }
    }

    /**
    * 获取版本名称
    */
    private fun getVersionName(): String {
        return try {
            context.packageManager.getPackageInfo(context.packageName, 0).versionName
        } catch (e: Exception) {
            "unknown"
        }
    }

    /**
    * 获取版本代码
    */
    private fun getVersionCode(): Long {
        return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
            try {
                context.packageManager.getPackageInfo(context.packageName, 0).longVersionCode
            } catch (e: Exception) {
                -1
            }
        } else {
            @Suppress("DEPRECATION")
            try {
                context.packageManager.getPackageInfo(context.packageName, 0).versionCode.toLong()
            } catch (e: Exception) {
                -1
            }
        }
    }

    /**
    * 获取构建时间
    */
    private fun getBuildTime(): String {
        return try {
            val appInfo = context.packageManager.getApplicationInfo(context.packageName, 0)
            val sdf = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
            sdf.format(Date(File(appInfo.sourceDir).lastModified()))
        } catch (e: Exception) {
            "unknown"
        }
    }

    /**
    * 通过反射获取静态字段值
    */
    private fun getStaticField(clazz: Class<*>, fieldName: String): String {
        return try {
            val field = clazz.getDeclaredField(fieldName)
            field.isAccessible = true
            field.get(null)?.toString() ?: "null"
        } catch (e: Exception) {
            "unknown"
        }
    }

    /**
    * 日志级别转换为单字符
    */
    private fun priorityToChar(priority: Int): Char = when (priority) {
        Log.VERBOSE -> 'V'
        Log.DEBUG -> 'D'
        Log.INFO -> 'I'
        Log.WARN -> 'W'
        Log.ERROR -> 'E'
        Log.ASSERT -> 'A'
        else -> '?'
    }
}